//
//  ARCTest.m
//  MacTestProject
//
//  Created by LiuLichen on 2022/5/6.
//

#import "ARCTest.h"

@implementation ARCTest {
    id __weak weakObj_;
    NSUInteger count_;
}

- (id) init {
    self = [super init];

    [self testStrongPtr];
    [self testWeakPtr];
    [self testUnsafeUnretainedPtr];
    [self testAutoreleasePtr];

    return self;
}

- (BOOL) retainWeakReference {
    if (++count_ > 3) {
        return NO;
    }
    return [super retainWeakReference];
}

- (void) testStrongPtr {
    id __strong obj0 = [[NSObject alloc] init];     // A
    id __strong obj1 = [[NSObject alloc] init];     // B
    id __strong obj2 = nil;

    obj0 = obj1;
    /**
     * obj0持有由obj1赋值的对象B的强引用
     * 因为obj0被赋值，所以原先持有的对对象A的强引用失效。
     * 对象A的所有者不存在，因此废弃对象A。
     *
     * 此时，持有对象B的强引用的变量为obj0和obj1.
     */
    obj2 = obj0;
    /**
     * 此时，持有对象B的强引用的变量为obj0 obj1 obj2
     */
    obj1 = nil;
    /**
     * 此时，持有对象B的强引用的变量为obj0 obj2
     */
    obj0 = nil;
    /**
     * 此时，持有对象B的强引用的变量为obj2
     */
    obj2 = nil;
    /**
     * 此时，对象B的所有者不存在，因此废弃对象B。
     */
}

- (void) testWeakPtr {
    id __weak obj1 = nil;
    {
        id __strong obj0 = [[NSObject alloc] init];
        obj1 = obj0;
        NSLog(@"%@", obj1);       // <NSObject: 0x101104a30>
    }
    NSLog(@"%@", obj1);           // (null)
    {
        id __weak obj = [[NSObject alloc] init];
        NSLog(@"%@", obj);        // (null)
    }
//    {
//        id __strong obj = [[ARCTest alloc] init];
//        id __weak o = obj;
//        NSLog(@"1 %@", o);          // <NSObject: 0x10131d030>
//        NSLog(@"2 %@", o);          // <NSObject: 0x10131d030>
//        NSLog(@"3 %@", o);          // <NSObject: 0x10131d030>
//        NSLog(@"4 %@", o);          // (null)
//        NSLog(@"5 %@", o);          // (null)
//    }
}

- (void) testUnsafeUnretainedPtr {
    id __unsafe_unretained obj1 = nil;
    {
        id __strong obj0 = [[NSObject alloc] init];
        obj1 = obj0;
        NSLog(@"%@", obj1);       // <NSObject: 0x101405260>
    }
    NSLog(@"%@", obj1);           // <NSObject: 0x101405260>
}

- (void) testAutoreleasePtr {
    {
//        id __strong obj = [[NSObject alloc] init];
//        @autoreleasepool {
//            id __autoreleasing o = obj;
//            NSLog(@"retain count = %d in @autoreleasepool", _objc_rootRetainCount(obj));        // 2
//        }
//        NSLog(@"retain count = %d", _objc_rootRetainCount(obj));        // 1
    }
}

@end
